package com.queming.core.service.file;

import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.http.HttpMethodName;
import com.qcloud.cos.http.HttpProtocol;
import com.qcloud.cos.region.Region;
import com.queming.core.dto.FileUploadDto;
import com.queming.core.exception.BizException;
import com.queming.core.exception.ExceptionType;
import com.tencent.cloud.CosStsClient;
import com.tencent.cloud.Response;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;


import java.net.URL;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

/**
 * @author chencidiao
 * @date 2022/05/04 13:44
 **/
@Service("COS")
public class CosStorageServiceImpl implements StorageService{

    @Value("${cos.bucket}")
    private String bucket;

    @Value("${cos.secretId}")
    private String secretId;

    @Value("${cos.secretKey}")
    private String secretKey;

    @Value("${cos.region}")
    private String region;
    @Override
    public FileUploadDto initFileUpload(){
        try {
            Response response = CosStsClient.getCredential(getCosStsConfig());
            FileUploadDto uploadDto = new FileUploadDto();
            uploadDto.setSecretId(response.credentials.tmpSecretId);
            uploadDto.setSecretKey(response.credentials.tmpSecretKey);
            uploadDto.setSessionToken(response.credentials.sessionToken);
            uploadDto.setStartTime(response.startTime);
            uploadDto.setExpiredTime(response.expiredTime);
            return uploadDto;
        }catch (Exception e){
            e.printStackTrace();
            throw new BizException(ExceptionType.INNER_ERROR);
        }
    }

    @Override
    public String getFileUri(String fileKey) {
        COSClient cosClient = createCOSClient();
        Date expirationDate = new Date(System.currentTimeMillis() + 30 * 60 * 1000);
        Map<String, String> params = new HashMap<String, String>();
        Map<String, String> headers = new HashMap<String, String>();
        HttpMethodName method = HttpMethodName.GET;
        URL url = cosClient.generatePresignedUrl(bucket, fileKey, expirationDate, method, headers, params);
        cosClient.shutdown();
        return url.toString();

    }

    COSClient createCOSClient(){
        // 这里需要已经获取到临时密钥的结果。
        // 临时密钥的生成参考 https://cloud.tencent.com/document/product/436/14048#cos-sts-sdk
        BasicCOSCredentials cred = new BasicCOSCredentials(secretId, secretKey);

        //包含了后序请求cos的客户端配置
        ClientConfig clientConfig = new ClientConfig();

        // 设置 bucket 的地域
        // COS_REGION 请参照 https://cloud.tencent.com/document/product/436/6224

        clientConfig.setRegion(new Region(region));

        // 设置请求协议, http 或者 https
        // 5.6.53 及更低的版本，建议设置使用 https 协议
        // 5.6.54 及更高版本，默认使用了 https
        clientConfig.setHttpProtocol(HttpProtocol.https);

        // 以下的设置，是可选的：

        // 设置 socket 读取超时，默认 30s
        clientConfig.setSocketTimeout(30 * 1000);
        // 设置建立连接超时，默认 30s
        clientConfig.setConnectionTimeout(30 * 1000);
        return new COSClient(cred,clientConfig);

    }

    /**
     *
     * @author 陈词调
     * @date 2022/5/4
     * 获取cos私有token时的配置
     */

    private TreeMap<String,Object> getCosStsConfig(){
        TreeMap<String, Object> config = new TreeMap<String, Object>();
        config.put("secretId",secretId);
        config.put("secretKey",secretKey);
        //零时密钥有效时长，单位是秒
        config.put("durationSeconds",1800);
        config.put("allowPrefixes",new String[]{"*"});
        config.put("bucket",bucket);
        config.put("region",region);
        String[] allowActions=new String[]{
                //简单上传
                "name/cos:PutObject",
                "name/cos:PostObject",
                //分片上传
                "name/cos:InitiateMultipartUpload",
                "name/cos:ListMultipartUploads",
                "name/cos:ListParts",
                "name/cos:UploadPart",
                "name/cos:CompleteMultipartUpload"
        };
        config.put("allowActions",allowActions);
        return config;
    }
}
